﻿using Manon.Repository.Collections;
using Manon.Repository.Extensions;
using Manon.Repository.Repository;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Query;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;

namespace Manon.Repository
{
    public class Repository<TEntity> : Repository<TEntity, int>, IRepository<TEntity, int> where TEntity : class, IAggregateRoot<int>
    {
        public Repository(ICommonDbContext dbContext) : base(dbContext)
        {

        }
    }

    /// <summary>
    /// 通用仓储的默认实现 默认都是NoTracking 
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    public class Repository<TEntity, TId> : IRepository<TEntity, TId> where TEntity : class, IAggregateRoot<TId>
    {
        protected readonly DbSet<TEntity> _dbSet;
        protected ICommonDbContext dbContext;
        public Repository(ICommonDbContext _dbContext)
        {
            dbContext = _dbContext;
            _dbSet = _dbContext.Set<TEntity>();
        }

        #region  查询


        #region 条件查询
        /// <summary>
        /// 根据条件查询，返回IQueryable<TEntity>
        /// </summary>
        /// <param name="where">查询添加，可以为空</param>
        /// <returns></returns>
        public IQueryable<TEntity> GetQuery()
        {
            Expression<Func<TEntity, bool>> where = FilterExtension.ToGovConditionExpression<TEntity>(dbContext.reposUser);
            var query = _dbSet.AsNoTracking().Where(where);
            return query; ;
        }

        /// <summary>
        /// 根据条件查询，返回IQueryable<TEntity>
        /// </summary>
        /// <param name="where">查询添加，可以为空</param>
        /// <returns></returns>
        public IQueryable<TEntity> GetQuery(Expression<Func<TEntity, bool>> where)
        {
            if (where == null)
            {
                where = FilterExtension.ToGovConditionExpression<TEntity>(dbContext.reposUser);
            }
            else
            {
                where = where.And(FilterExtension.ToGovConditionExpression<TEntity>(dbContext.reposUser));
            }

            var query = _dbSet.AsNoTracking();
            if (where == null)
            {
                return query;
            }
            return query.Where(where);
        }

        /// <summary>
        /// 根据条件查询，返回IQueryable<TEntity>
        /// </summary>
        /// <param name="where">查询添加，可以为空</param>
        /// <returns></returns>
        public IQueryable<TSelector> GetQuery<TSelector>(Expression<Func<TEntity, TSelector>> selector)
        {
            var query = GetQuery();

            return query.Select(selector);
        }

        /// <summary>
        /// 根据条件查询，返回IQueryable<TEntity>
        /// </summary>
        /// <param name="where">查询添加，可以为空</param>
        /// <returns></returns>
        public IQueryable<TSelector> GetQuery<TSelector>(Expression<Func<TEntity, bool>> where, Expression<Func<TEntity, TSelector>> selector)
        {
            var query = GetQuery(where);

            return query.Select(selector);
        }


        ///// <summary>
        ///// 根据条件查询，返回IQueryable<TEntity>
        ///// </summary>
        ///// <param name="where">查询添加，可以为空</param>
        ///// <returns></returns>
        //public IQueryable<TEntity> GetQueryInclude<TSelector, TProperty>(Expression<Func<TEntity, bool>> where, Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> include)
        //{

        //    var query = GetQuery(where);
        //    return include(query);
        //}

        /// <summary>
        /// 根据条件查询，返回IQueryable<TEntity>
        /// </summary>
        /// <param name="where">查询添加，可以为空</param>
        /// <returns></returns>
        public IQueryable<TSelector> GetQueryInclude<TSelector, TProperty>(Expression<Func<TEntity, bool>> where, Expression<Func<TEntity, TSelector>> selector, Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> include)
        {
            var query = GetQuery();
            if (include != null)
            {
                query = include(query);
            }

            return query.Where(where).Select(selector);
        }



        /// <summary>
        /// 根据条件查询，返回IQueryable,不可追踪<TEntity>
        /// </summary>
        /// <param name="where">查询添加，可以为空</param>
        /// <returns></returns>
        public IQueryable<TEntity> GetQueryAsNoFilter()
        {
            var query = _dbSet.IgnoreQueryFilters<TEntity>().AsNoTracking();
            return query;
        }


        /// <summary>
        /// 根据条件查询，返回IQueryable,不可追踪<TEntity>
        /// </summary>
        /// <param name="where">查询添加，可以为空</param>
        /// <returns></returns>
        public IQueryable<TEntity> GetQueryAsNoFilter(Expression<Func<TEntity, bool>> where)
        {
            var query = _dbSet.IgnoreQueryFilters<TEntity>().AsNoTracking();
            if (where == null) return query;

            return query.Where(where);
        }


        /// <summary>
        /// 异步条件查询，返回实体集合. 状态不可追踪
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public async Task<IEnumerable<TEntity>> GetListAsync(CancellationToken cancellationToken = default)
        {
            return await GetQuery().ToListAsync(cancellationToken);
        }


        /// <summary>
        /// 异步条件查询，返回实体集合. 状态不可追踪
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public async Task<IEnumerable<TSelector>> GetListAsync<TSelector>(Expression<Func<TEntity, TSelector>> selector, CancellationToken cancellationToken = default)
        {
            return await GetQuery(selector).ToListAsync(cancellationToken);
        }

        /// <summary>
        /// 异步条件查询，返回实体集合. 状态不可追踪
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public async Task<IEnumerable<TSelector>> GetListIncludeAsync<TSelector>(Expression<Func<TEntity, bool>> where, Expression<Func<TEntity, TSelector>> selector, Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> include, CancellationToken cancellationToken = default)
        {
            var query = GetQuery();
            if (include != null)
            {
                query = include(query);
            }

            return await query.Where(where).Select(selector).ToListAsync(cancellationToken);
        }

        /// <summary>
        /// 异步条件查询，返回实体集合. 状态不可追踪
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public async Task<IEnumerable<TEntity>> GetListIncludeOnlyAsync<TProperty>(Expression<Func<TEntity, bool>> where, Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, TProperty>> include, CancellationToken cancellationToken = default)
        {
            var query = GetQuery();
            if (include != null)
            {
                query = include(query);
            }

            return await query.Where(where).ToListAsync(cancellationToken);
        }

        /// <summary>
        /// 异步条件查询，返回实体集合. 状态不可追踪
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public async Task<IEnumerable<TEntity>> GetListAsync(Expression<Func<TEntity, bool>> where, CancellationToken cancellationToken = default)
        {
            return await GetQuery(where).ToListAsync(cancellationToken);
        }



        /// <summary>
        /// 异步条件查询，返回实体集合. 状态不可追踪
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public async Task<IEnumerable<TSelector>> GetListAsync<TSelector>(Expression<Func<TEntity, bool>> where, Expression<Func<TEntity, TSelector>> selector, CancellationToken cancellationToken = default)
        {
            return await GetQuery(where, selector).ToListAsync(cancellationToken);
        }


        /// <summary>
        /// 异步条件查询，返回实体集合. 状态不可追踪
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public async Task<IEnumerable<TEntity>> GetListAsNoFilterAsync(CancellationToken cancellationToken = default)
        {
            return await GetQueryAsNoFilter().ToListAsync(cancellationToken);
        }

        /// <summary>
        /// 异步条件查询，返回实体集合. 状态不可追踪
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public async Task<IEnumerable<TEntity>> GetListAsNoFilterAsync(Expression<Func<TEntity, bool>> where, CancellationToken cancellationToken = default)
        {
            return await GetQueryAsNoFilter(where).ToListAsync(cancellationToken);
        }

        /// <summary>
        /// 异步条件查询，返回自定义实体集合. 状态不可追踪
        /// </summary>
        /// <typeparam name="TTarget"></typeparam>
        /// <param name="where"></param>
        /// <returns></returns>
        public async Task<IEnumerable<TTarget>> GetListAsync<TTarget>()
        {
            IEnumerable<TEntity> entities = await GetQuery().ToListAsync();

            return ObjectConvertExtensions.ConvertTo<TEntity, TTarget>(entities);
        }

        /// <summary>
        /// 异步条件查询，返回自定义实体集合. 状态不可追踪
        /// </summary>
        /// <typeparam name="TTarget"></typeparam>
        /// <param name="where"></param>
        /// <returns></returns>
        public async Task<IEnumerable<TTarget>> GetListAsync<TTarget>(Expression<Func<TEntity, bool>> where)
        {
            IEnumerable<TEntity> entities = await GetQuery(where).ToListAsync();

            return ObjectConvertExtensions.ConvertTo<TEntity, TTarget>(entities);
        }

        /// <summary>
        /// 异步条件查询，返回自定义实体集合. 状态不可追踪
        /// </summary>
        /// <typeparam name="TTarget"></typeparam>
        /// <param name="where"></param>
        /// <returns></returns>
        public async Task<IEnumerable<TTarget>> GetListAsNoFilterAsync<TTarget>(Expression<Func<TEntity, bool>> where)
        {
            IEnumerable<TEntity> entities = await GetQueryAsNoFilter(where).ToListAsync();

            return ObjectConvertExtensions.ConvertTo<TEntity, TTarget>(entities);
        }
        #endregion

        #region 查询单条记录 

        /// <summary>
        /// 异步查询单条记录 ,状态不可追踪
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<TEntity?> GetFirstOrDefaultAsync(CancellationToken cancellationToken = default(CancellationToken))
        {
            IQueryable<TEntity> query = GetQuery();

            return await query.FirstOrDefaultAsync(cancellationToken);

        }
        /// <summary>
        /// 异步查询单条记录 ,状态不可追踪
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<TSelector?> GetFirstOrDefaultAsync<TSelector>(Expression<Func<TEntity, TSelector>> selector, CancellationToken cancellationToken = default(CancellationToken))
        {
            IQueryable<TSelector> query = GetQuery(selector);

            return await query.FirstOrDefaultAsync(cancellationToken);

        }

        /// <summary>
        /// 异步查询单条记录 ,状态不可追踪
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<TEntity?> GetFirstOrDefaultAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default(CancellationToken))
        {
            IQueryable<TEntity> query = GetQuery(predicate);

            return await query.FirstOrDefaultAsync(cancellationToken);

        }


        /// <summary>
        /// 异步查询单条记录 ,状态不可追踪
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<TSelector?> GetFirstOrDefaultAsync<TSelector>(Expression<Func<TEntity, bool>> predicate, Expression<Func<TEntity, TSelector>> selector, CancellationToken cancellationToken = default(CancellationToken))
        {
            IQueryable<TSelector> query = GetQuery(predicate, selector);

            return await query.FirstOrDefaultAsync(cancellationToken);

        }

        /// <summary>
        ///  异步查询单条记录 ,状态不可追踪
        /// </summary>
        /// <typeparam name="TTarget"></typeparam>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<TTarget?> GetFirstOrDefaultAsync<TTarget>(Expression<Func<TEntity, bool>> predicate = null, CancellationToken cancellationToken = default)
        {
            IQueryable<TEntity> query = GetQuery(predicate);

            var result = await query.FirstOrDefaultAsync(cancellationToken);
            if (result == null) return default(TTarget);

            return ObjectConvertExtensions<TEntity, TTarget>.ConvertTo(result);
        }

        /// <summary>
        /// 异步查询单条记录 ,状态不可追踪
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<TEntity?> GetFirstOrDefaultAsNoFilterAsync(Expression<Func<TEntity, bool>> predicate = null, CancellationToken cancellationToken = default)
        {
            IQueryable<TEntity> query = GetQueryAsNoFilter(predicate);

            return await query.FirstOrDefaultAsync(cancellationToken);
        }

        /// <summary>
        ///  异步查询单条记录 ,状态不可追踪
        /// </summary>
        /// <typeparam name="TTarget"></typeparam>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<TTarget?> GetFirstOrDefaultAsNoFilterAsync<TTarget>(Expression<Func<TEntity, bool>> predicate = null, CancellationToken cancellationToken = default)
        {
            IQueryable<TEntity> query = GetQueryAsNoFilter(predicate);

            var result = await query.FirstOrDefaultAsync(cancellationToken);
            if (result == null) return default(TTarget);

            return ObjectConvertExtensions<TEntity, TTarget>.ConvertTo(result);
        }


        #endregion

        #endregion


        #region  count、exist

        /// <summary>
        /// 异步查询记录数
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<int> CountAsync(Expression<Func<TEntity, bool>> predicate = null, CancellationToken cancellationToken = default)
        {
            return await GetQuery(predicate).CountAsync(cancellationToken);
        }



        /// <summary>
        /// 异步查询是否存在
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> ExistsAsync(Expression<Func<TEntity, bool>> predicate = null, CancellationToken cancellationToken = default)
        {
            return await GetQuery(predicate).AnyAsync(cancellationToken);
        }



        /// <summary>
        /// 异步查询记录数，忽略全局过滤
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<int> CountAsNoFilterAsync(Expression<Func<TEntity, bool>> predicate = null, CancellationToken cancellationToken = default)
        {
            return await GetQueryAsNoFilter(predicate).CountAsync(cancellationToken);
        }

        /// <summary>
        /// 异步查询是否存在，忽略全局过滤
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> ExistsAsNoFilterAsync(Expression<Func<TEntity, bool>> predicate = null, CancellationToken cancellationToken = default)
        {
            return await GetQueryAsNoFilter(predicate).AnyAsync(cancellationToken);
        }
        #endregion



        #region 排序

        /// <summary>
        /// 排序 正序
        /// </summary>
        /// <param name="orderBy"></param>
        /// <returns></returns> 
        public IOrderedQueryable<TEntity> OrderBy(Expression<Func<TEntity, TId>> keySelector)
        {
            return GetQuery().OrderBy(keySelector);
        }

        /// <summary>
        /// 排序 倒序
        /// </summary>
        /// <param name="orderBy"></param>
        /// <returns></returns>
        public IOrderedQueryable<TEntity> OrderByDescending(Expression<Func<TEntity, TId>> keySelector)
        {
            return GetQuery().OrderByDescending(keySelector);
        }


        #endregion

        #region GetPagedList



        /// <summary>
        /// 异步获取分页
        /// </summary>
        /// <param name="where">条件</param>
        /// <param name="Input">分页参数</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<PagedList<TEntity>> GetPagedListAsync(Expression<Func<TEntity, bool>> where, BasePageInput Input, CancellationToken cancellationToken = default)
        {
            IQueryable<TEntity> query = GetQuery(where);

            return await query.ToPagedListAsync(Input, cancellationToken);
        }

        /// <summary>
        /// 异步获取分页
        /// </summary>
        /// <param name="where">条件</param>
        /// <param name="Input">分页参数</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<PagedList<TSelector>> GetPagedListAsync<TSelector>(Expression<Func<TEntity, bool>> where, BasePageInput Input, Expression<Func<TEntity, TSelector>> selector, CancellationToken cancellationToken = default)
        {
            IQueryable<TSelector> query = GetQuery(where, selector);

            return await query.ToPagedListAsync(Input, cancellationToken);
        }



        /// <summary>
        /// 异步获取分页列表，并返回指定的TResult类型
        /// </summary>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="where">条件</param>
        /// <param name="Input">分页参数</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<PagedList<TResult>> GetPagedListAsync<TResult>(Expression<Func<TEntity, bool>> where, BasePageInput Input, CancellationToken cancellationToken = default)
        {
            IQueryable<TEntity> query = GetQuery(where);

            return await query.ToPagedListAsync<TResult, TEntity>(Input, cancellationToken);
        }



        /// <summary>
        /// 异步获取分页列表，并返回指定的TResult类型
        /// </summary>
        /// <typeparam name="TResult"></typeparam> 
        /// <param name="Input">分页参数</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<PagedList<TResult>> GetPagedListAsync<TResult>(BasePageInput Input, CancellationToken cancellationToken = default)
        {
            IQueryable<TEntity> query = GetQuery();

            return await query.ToPagedListAsync<TResult, TEntity>(Input, cancellationToken);
        }

        /// <summary>
        /// 异步获取分页
        /// </summary>
        /// <param name="where">条件</param>
        /// <param name="Input">分页参数</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<PagedList<TEntity>> GetPagedListAsNoFilterAsync(Expression<Func<TEntity, bool>> where, BasePageInput Input, CancellationToken cancellationToken = default)
        {
            IQueryable<TEntity> query = GetQueryAsNoFilter(where);


            return await query.ToPagedListAsync(Input, cancellationToken);
        }

        /// <summary>
        /// 异步获取分页列表，并返回指定的TResult类型
        /// </summary>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="where">条件</param>
        /// <param name="Input">分页参数</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<PagedList<TResult>> GetPagedListAsNoFilterAsync<TResult>(Expression<Func<TEntity, bool>> where, BasePageInput Input, CancellationToken cancellationToken = default)
        {
            IQueryable<TEntity> query = GetQueryAsNoFilter(where);

            return await query.ToPagedListAsync<TResult, TEntity>(Input, cancellationToken);
        }

        /// <summary>
        /// 异步获取分页列表，并返回指定的TResult类型
        /// </summary>
        /// <typeparam name="TResult"></typeparam> 
        /// <param name="Input">分页参数</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<PagedList<TResult>> GetPagedListAsNoFilterAsync<TResult>(BasePageInput Input, CancellationToken cancellationToken = default)
        {
            IQueryable<TEntity> query = GetQueryAsNoFilter();

            return await query.ToPagedListAsync<TResult, TEntity>(Input, cancellationToken);
        }

        #endregion






        #region Insert

        public ValueTask<EntityEntry<TEntity>> InsertAsync(TEntity entity, CancellationToken cancellationToken = default(CancellationToken))
        {
            EntityProperties properties = new EntityProperties().GetEntityProperty<TEntity>();
            IList<PropertyInfo> propertyWithColumnAttributes = EntityPropertiesCache.GetPropertyWithColumnAttributes<TEntity>();
            if (propertyWithColumnAttributes != null && propertyWithColumnAttributes.Any())
            {
                foreach (var attr in propertyWithColumnAttributes)
                {
                    attr.SetValue(entity, EntityProperties.GetColumnValue(attr), null);
                }
            }

            if (properties.PiCreateTime != null) properties.PiCreateTime.SetValue(entity, DateTime.Now, null);
            if (properties.PiUpdateTime != null) properties.PiUpdateTime.SetValue(entity, DateTime.Now, null);


            return _dbSet.AddAsync(entity, cancellationToken);
        }

        public ValueTask<EntityEntry<TEntity>> InsertAsync(TEntity entity, object userId, CancellationToken cancellationToken = default(CancellationToken))
        {
            EntityProperties properties = new EntityProperties().GetEntityProperty<TEntity>();
            IList<PropertyInfo> propertyWithColumnAttributes = EntityPropertiesCache.GetPropertyWithColumnAttributes<TEntity>();
            if (propertyWithColumnAttributes != null && propertyWithColumnAttributes.Any())
            {
                foreach (var attr in propertyWithColumnAttributes)
                {
                    attr.SetValue(entity, EntityProperties.GetColumnValue(attr), null);
                }
            }
            if (properties.PiCreateTime != null) properties.PiCreateTime.SetValue(entity, DateTime.Now, null);
            if (properties.PiCreateBy != null) properties.PiCreateBy.SetValue(entity, userId, null);
            if (properties.PiUpdateTime != null) properties.PiUpdateTime.SetValue(entity, DateTime.Now, null);
            if (properties.PiUpdateBy != null) properties.PiUpdateBy.SetValue(entity, userId, null);

            return _dbSet.AddAsync(entity, cancellationToken);
        }



        public Task InsertAsync(IEnumerable<TEntity> entities, CancellationToken cancellationToken = default(CancellationToken))
        {
            EntityProperties properties = new EntityProperties().GetEntityProperty<TEntity>();
            IList<PropertyInfo> propertyWithColumnAttributes = EntityPropertiesCache.GetPropertyWithColumnAttributes<TEntity>();
            foreach (var entity in entities)
            {
                if (propertyWithColumnAttributes != null && propertyWithColumnAttributes.Any())
                {
                    foreach (var attr in propertyWithColumnAttributes)
                    {
                        attr.SetValue(entity, EntityProperties.GetColumnValue(attr), null);
                    }
                }
                if (properties.PiCreateTime != null) properties.PiCreateTime.SetValue(entity, DateTime.Now, null);
                if (properties.PiUpdateTime != null) properties.PiUpdateTime.SetValue(entity, DateTime.Now, null);
            }
            return _dbSet.AddRangeAsync(entities, cancellationToken);
        }
        public Task InsertAsync(IEnumerable<TEntity> entities, object userId, CancellationToken cancellationToken = default(CancellationToken))
        {
            EntityProperties properties = new EntityProperties().GetEntityProperty<TEntity>();
            IList<PropertyInfo> propertyWithColumnAttributes = EntityPropertiesCache.GetPropertyWithColumnAttributes<TEntity>();
            foreach (var entity in entities)
            {
                if (propertyWithColumnAttributes != null && propertyWithColumnAttributes.Any())
                {
                    foreach (var attr in propertyWithColumnAttributes)
                    {
                        attr.SetValue(entity, EntityProperties.GetColumnValue(attr), null);
                    }
                }
                if (properties.PiCreateTime != null) properties.PiCreateTime.SetValue(entity, DateTime.Now, null);
                if (properties.PiCreateBy != null) properties.PiCreateBy.SetValue(entity, userId, null);
                if (properties.PiUpdateTime != null) properties.PiUpdateTime.SetValue(entity, DateTime.Now, null);
                if (properties.PiUpdateBy != null) properties.PiUpdateBy.SetValue(entity, userId, null);
            }
            return _dbSet.AddRangeAsync(entities, cancellationToken);
        }
        #endregion

        #region Update



        public Task UpdateAsync<TSelector>(TEntity entity, Expression<Func<TEntity, TSelector>> selector)
        {
            if (entity == null) return Task.CompletedTask;

            if (selector == null) return Task.CompletedTask;

            _dbSet.Attach(entity);

            EntityProperties properties = new EntityProperties().GetEntityProperty<TEntity>();

            if (properties.PiUpdateTime != null) properties.PiUpdateTime.SetValue(entity, DateTime.Now, null);

            var entry = this.dbContext.SetEntry<TEntity>(entity);
            var body = selector.Body;
            var memberExp = (NewExpression)body;
            var members = memberExp.Members;
            if (members != null)
            {
                foreach (var member in members)
                {
                    entry.Property(member.Name).IsModified = true;
                }
            }

            return Task.CompletedTask;
        }
        public Task UpdateAsync<TSelector>(IEnumerable<TEntity> entities, Expression<Func<TEntity, TSelector>> selector)
        {
            if (entities == null || !entities.Any()) return Task.CompletedTask;

            var body = selector.Body;
            var memberExp = (NewExpression)body;
            var members = memberExp.Members;

            _dbSet.AttachRange(entities);

            EntityProperties properties = new EntityProperties().GetEntityProperty<TEntity>();
            foreach (var entity in entities)
            {
                if (properties.PiUpdateTime != null) properties.PiUpdateTime.SetValue(entity, DateTime.Now, null);

                var entry = this.dbContext.SetEntry<TEntity>(entity);
                if (members != null)
                {
                    foreach (var member in members)
                    {
                        entry.Property(member.Name).IsModified = true;
                    }
                }

            }
            return Task.CompletedTask;
        }



        public Task UpdateAsync(TEntity entity)
        {
            if (entity == null) return Task.CompletedTask;

            EntityProperties properties = new EntityProperties().GetEntityProperty<TEntity>();

            if (properties.PiUpdateTime != null) properties.PiUpdateTime.SetValue(entity, DateTime.Now, null);

            this.dbContext.SetEntry<TEntity>(entity, EntityState.Modified);
            _dbSet.Update(entity);
            return Task.CompletedTask;
        }



        public Task UpdateAsync(IEnumerable<TEntity> entities)
        {
            if (entities == null || !entities.Any()) return Task.CompletedTask;

            EntityProperties properties = new EntityProperties().GetEntityProperty<TEntity>();
            foreach (var entity in entities)
            {
                if (properties.PiUpdateTime != null) properties.PiUpdateTime.SetValue(entity, DateTime.Now, null);

                this.dbContext.SetEntry<TEntity>(entity, EntityState.Modified);
            }

            _dbSet.UpdateRange(entities);
            return Task.CompletedTask;
        }

        public Task UpdateAsync(TEntity entity, object userId)
        {
            if (entity == null) return Task.CompletedTask;

            EntityProperties properties = new EntityProperties().GetEntityProperty<TEntity>();
            if (properties.PiUpdateTime != null) properties.PiUpdateTime.SetValue(entity, DateTime.Now, null);
            if (properties.PiUpdateBy != null) properties.PiUpdateBy.SetValue(entity, userId, null);

            this.dbContext.SetEntry<TEntity>(entity, EntityState.Modified);
            _dbSet.Update(entity);
            return Task.CompletedTask;
        }


        public Task UpdateAsync(IEnumerable<TEntity> entities, object userId)
        {
            if (entities == null || !entities.Any()) return Task.CompletedTask;

            EntityProperties properties = new EntityProperties().GetEntityProperty<TEntity>();
            foreach (var entity in entities)
            {
                if (properties.PiUpdateTime != null) properties.PiUpdateTime.SetValue(entity, DateTime.Now, null);
                if (properties.PiUpdateBy != null) properties.PiUpdateBy.SetValue(entity, userId, null);

                this.dbContext.SetEntry<TEntity>(entity, EntityState.Modified);
            }

            _dbSet.UpdateRange(entities);
            return Task.CompletedTask;
        }
        #endregion

        #region Delete

        public Task DeleteAsync(TEntity entity)
        {
            this.dbContext.SetEntry<TEntity>(entity, EntityState.Deleted);
            _dbSet.Remove(entity);
            return Task.CompletedTask;
        }



        public async Task DeleteAsync(object id)
        {
            var entity = _dbSet.Find(id);
            if (entity != null)
            {
                await DeleteAsync(entity);
            }
            await Task.CompletedTask;
        }

        public Task DeleteAsync(IEnumerable<TEntity> entities)
        {
            if (entities == null || !entities.Any()) return Task.CompletedTask;
            foreach (var entity in entities)
            {
                this.dbContext.SetEntry<TEntity>(entity, EntityState.Deleted);
            }
            _dbSet.RemoveRange(entities);
            return Task.CompletedTask;
        }

        public Task DeleteLogicAsync(IEnumerable<TEntity> entities, object userId = null)
        {
            if (entities == null || !entities.Any()) return Task.CompletedTask;

            EntityProperties properties = new EntityProperties().GetEntityProperty<TEntity>();

            foreach (var entity in entities)
            {
                if (properties.PiDeleteBy != null) properties.PiDeleteBy.SetValue(entity, userId, null);
                if (properties.PiDeleteTime != null) properties.PiDeleteTime.SetValue(entity, DateTime.Now, null);
                if (properties.PiIsDeleted != null) properties.PiIsDeleted.SetValue(entity, true, null);

                _dbSet.Attach(entity).State = EntityState.Modified;
            }
            return Task.CompletedTask;
        }
        public Task DeleteLogicAsync(TEntity entity, object userId = null)
        {

            EntityProperties properties = new EntityProperties().GetEntityProperty<TEntity>();

            if (properties.PiDeleteBy != null) properties.PiDeleteBy.SetValue(entity, userId, null);
            if (properties.PiDeleteTime != null) properties.PiDeleteTime.SetValue(entity, DateTime.Now, null);
            if (properties.PiIsDeleted != null) properties.PiIsDeleted.SetValue(entity, true, null);

            _dbSet.Attach(entity).State = EntityState.Modified;

            return Task.CompletedTask;
        }

        public async Task DeleteLogicAsync(object id, object userId = null)
        {
            var entity = _dbSet.Find(id);
            if (entity != null)
            {
                await DeleteLogicAsync(entity, userId);
            }
            await Task.CompletedTask;
        }


        #endregion




        #region sql相关
        /// <summary>
        /// 执行原生sql语句 
        /// </summary>
        /// <param name="sql">sql语句</param>
        /// <param name="parameters">参数</param>
        /// <returns></returns>
        public async Task<int> ExecuteSqlCommandAsync(string sql, params object[] parameters)
        {
            return await dbContext.Database.ExecuteSqlRawAsync(sql, parameters);
        }


        #endregion


        public async Task<string> GetNo<Tentity>(int length)
        {
            return "";
        }

    }
}
